package cn.wizzer.app.user.modules.service.impl;

import cn.wizzer.app.sys.modules.models.SysParam;
import cn.wizzer.app.sys.modules.services.SysParamService;
import cn.wizzer.app.user.modules.models.GroupInfo;
import cn.wizzer.app.user.modules.models.GroupLog;
import cn.wizzer.app.user.modules.models.GroupMember;
import cn.wizzer.app.user.modules.models.constant.ChatConstant;
import cn.wizzer.app.user.modules.models.enums.MsgTypeEnum;
import cn.wizzer.app.user.modules.models.enums.OprTypeEnum;
import cn.wizzer.app.user.modules.models.enums.RedPacketStatusEnum;
import cn.wizzer.app.user.modules.models.vo.GroupLogVo;
import cn.wizzer.app.user.modules.services.GroupInfoService;
import cn.wizzer.app.user.modules.services.GroupLogService;
import cn.wizzer.app.user.modules.services.GroupMemberService;
import cn.wizzer.framework.base.model.enums.BizExceptionEnum;
import cn.wizzer.framework.base.service.BaseServiceImpl;
import cn.wizzer.framework.base.service.CommonDBService;
import cn.wizzer.framework.page.Pagination;
import cn.wizzer.framework.util.Result;
import cn.wizzer.framework.util.ThreadUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@IocBean(args = {"refer:dao"})
@Service(interfaceClass = GroupLogService.class)
public class GroupLogServiceImpl extends BaseServiceImpl<GroupLog> implements GroupLogService {
    public GroupLogServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private CommonDBService dbService;
    @Inject
    private GroupMemberService groupMemberService;
    @Inject
    private GroupInfoService groupInfoService;
    @Inject
    @Reference
    private SysParamService sysParamService;
    @Inject
    private RedisService redisService;

    @Override
    public Pagination listPage(Integer pageNumber, Integer pageSize, String groupId) {
        Sql sql = Sqls.create("SELECT gl.manager,gl.id, gl.groupId, gl.ctAt, gl.userId, gl.oprType, gl.msgType, gl.content, " +
                " u.nickName,u.headPicture " +
                " FROM group_log gl" +
                " LEFT JOIN user u ON u.id = gl.userId " +
                " $condition ");
        Cnd cnd = Cnd.where("gl.groupId", "=", groupId);
        sql.setCondition(cnd);
        sql.appendSourceSql("ORDER BY gl.ctAt DESC ");
        return dbService.listPage(GroupLogVo.class, pageNumber, pageSize, sql.toString());
    }

    @Aop(TransAop.READ_COMMITTED)
    @Override
    public Map<String, Object> groupSend(String sendUserId, String groupId, String content, MsgTypeEnum type, OprTypeEnum oprType, boolean isDel) {
        GroupInfo groupInfo = groupInfoService.fetch(groupId);
        if (groupInfo == null) {
            Result.breakWith(BizExceptionEnum.NOT_CHOOSE_GROUP);
        }
        // 判断是不是红包，如果不是红包，则要判断是否被禁言
        // Red**Envelopes **Envelopes
        if (!content.contains("**Envelopes")) {
            if (!groupInfo.getMasterId().equals(sendUserId) && groupInfo.isDisabled()) {
                Result.breakWith(BizExceptionEnum.GROUP_MUTED);
            }
        }
        //判断自己是否还在群里
        GroupMember member = groupMemberService.fetch(Cnd.where("groupId", "=", groupId).and("userId", "=", sendUserId).and("delFlag", "=", 0));
        if (member == null) {
            Result.breakWith(BizExceptionEnum.NOT_IN_THE_GROUP);
        }

        //创建群消息记录
        GroupLog create = GroupLog.create(groupId, sendUserId, oprType, type, content, member.getManager());
        // 更新最后通信时间
        groupInfoService.update(Chain.make("lastCommunicationTime", Times.getTS()), Cnd.where("id", "=", groupInfo.getId()));

        // 只插入群消息
        GroupLog groupLog = this.insert(create);
        // 1、查询出群里面的人
        List<GroupMember> groupMemberList = groupMemberService.listOnline(groupId);
        // 2、设置未读 这里循环会比较慢 异步执行
        ThreadUtil.execute(() -> {
            // 给群里面的所有人设置未读
            for (GroupMember groupMember : groupMemberList) {
                String redisKey = ChatConstant.UG + ":" + groupMember.getUserId() + ":" + groupId;
                String flag = redisService.get(redisKey);
                if (Strings.isNotBlank(flag)) {
                    if ("true".equals(flag)) {
                        redisService.set(redisKey, "false");
                    }
                } else {
                    redisService.set(redisKey, "false");
                }
            }
        });
        Map<String, Object> map = new HashMap<>();
        map.put("groupLog", groupLog);
        map.put("groupMemberList", groupMemberList);
        return map;
    }

    @Override
    public String groupReadFlag(String userId) {
        // 原来前端接口接收的就是数字字符串
        String readFlag = "0";
        // 查询出用户所有群
        List<GroupMember> listMember = groupMemberService.listMember(userId);
        for (GroupMember groupMember : listMember) {
            Map map = new HashMap();
            String redisKey = ChatConstant.UG + ":" + groupMember.getUserId() + ":" + groupMember.getGroupId();
            String flag = redisService.get(redisKey);
            if ("false".equals(flag)) {
                readFlag = "1";
                break;
            }
        }
        return readFlag;
    }

    @Override
    public void delLog(String groupId) {
        List<GroupLog> list = this.query(Cnd.where("groupId", "=", groupId));
        for (GroupLog log : list) {
            this.delete(log.getId());
        }
    }

    @Override
    public void delLogJob() {
        SysParam sysParam = sysParamService.fetch();
        // 全局参数获取群聊记录保存天数
        Double keepDayNumber = sysParam.getGroupLogKeepDayNumber();
        if (keepDayNumber > 0) {
            // 保存时间换算小时
            long keepTimestamp = new Double(keepDayNumber * 24 * 60 * 60).longValue();
            // 保存开始时间 = 当前时间 - 保存时间
            long keepStartTime = Times.getTS() - keepTimestamp;
            // 删除记录
            Sql sql = Sqls.create("DELETE FROM group_log WHERE ctAt < @time").setParam("time", keepStartTime);
            this.execute(sql);
        }
    }

    @Override
    public void updateRedPacket(String redPacketId, RedPacketStatusEnum statusEnum) {
        StringBuffer sb = new StringBuffer();
        sb.append("select * from group_log where content like '%");
        sb.append(redPacketId);
        sb.append("%'");
        List<GroupLog> list = dbService.list(GroupLog.class, sb.toString());
        if (list.size() > 0) {
            GroupLog groupLog = list.get(0);
            groupLog.setContent(groupLog.getContent().replace(RedPacketStatusEnum.OPENDING.toString(), statusEnum.toString()));
            this.update(groupLog);
        }
    }


}
